package com.sky.service.user.impl;

import com.alibaba.fastjson.JSON;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.BaseException;
import com.sky.mapper.MerchantMapper;
import com.sky.mapper.user.AddressBookMapper;
import com.sky.mapper.user.OrderDetailMapper;
import com.sky.mapper.user.UserOrderMapper;
import com.sky.mapper.user.ShoppingCartMapper;
import com.sky.pojo.*;
import com.sky.service.WebSocketServer;
import com.sky.service.user.UserOrderService;
import com.sky.utils.MapUtils;
import com.sky.vo.OrderSubmitVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class UserOrderServiceImpl implements UserOrderService {
    @Autowired
    private ShoppingCartMapper cartMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private UserOrderMapper userOrderMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    public LocalDateTime getEstimatedDeliveryTime(String customerAddress, Long shopId) {
        //预计送达时间=当前时间+菜品制作时间+配送时间+预留时间(10分钟)
        //获取菜品制作时间，购物车里面的数据
        Integer makeTime=cartMapper.getMakeTime(BaseContext.getCurrentId());
        //查询商家地址
        Merchant merchant = merchantMapper.getById(shopId);
        Map<String, String> map = MapUtils.gaodeTwoPointCostDistanceAndTimeByAddress(customerAddress, merchant.getShopAddress());
        String duration = map.get("duration");
        //计算总共耗时，秒
        Long time=makeTime*60+Long.parseLong(duration)+600;
        LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(time);
        return localDateTime;
    }

    /**
     * 提交订单
     * @param submitDTO
     * @return
     */
    @Transactional
    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO submitDTO) {
        //分布式锁
        String key = "ORDER-CREATE:"+BaseContext.getCurrentId();
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "aaa", Duration.ofSeconds(10));
        if (!flag){
            log.info("获取锁失败");
            throw new BaseException("请勿重复提交订单");
        }
        log.info("获取锁,开始执行");
        /*OrderSubmitVO result = new OrderSubmitVO();*/
        //本质是存两张表：订单表和订单明细表 先存订单表，然后获取订单id，再存订单明细表
        //所有的逻辑就一个，封装表里面需要的数据
        log.info("订单提交：{}",submitDTO);
        //异常处理
        AddressBook address = addressBookMapper.getById(submitDTO.getAddressBookId());
        if (address==null){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        Orders orders = new Orders();
        BeanUtils.copyProperties(submitDTO, orders);
        orders.setNumber(UUID.randomUUID().toString());
        orders.setUserId(BaseContext.getCurrentId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        orders.setAmount(submitDTO.getAmount());//这里暂时用前端给的订单金额测试，但实际开发中禁止使用前端给的金额

        log.info("订单信息：{}",orders);
        AddressBook addressBook = addressBookMapper.getById(submitDTO.getAddressBookId());
        if (addressBook==null){
            throw new BaseException("地址信息有误");
        }
        orders.setUserName(addressBook.getConsignee());
        orders.setConsignee(addressBook.getConsignee());//这里测试数据暂时用地址中的收货人名字
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getProvinceName()+addressBook.getCityName()+addressBook.getDistrictName()+addressBook.getDetail());
        log.info("地址信息：{}",addressBook);
        //出餐时间：当前时间+菜品制作时间
        Integer makeTime=cartMapper.getMakeTime(BaseContext.getCurrentId());
        orders.setMealTime(LocalDateTime.now().minusMinutes(makeTime));
        orders.setStatus(Orders.PENDING_PAYMENT);
        userOrderMapper.insert(orders);
        log.info("订单id：{}",orders.getId());
        //插入订单明细表
        List< ShoppingCart> shoppingCarts=cartMapper.getByUserId(BaseContext.getCurrentId());
        ArrayList<OrderDetail> orderDetailList = new ArrayList<>();
        if (CollectionUtils.isEmpty(shoppingCarts)){
            throw new BaseException("购物车为空");
        }
        log.info("订单明细：{}",shoppingCarts);
        for (ShoppingCart shoppingCart : shoppingCarts) {
            OrderDetail detail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart, detail);
            detail.setOrderId(orders.getId());
            orderDetailList.add(detail);
        }
        log.info("订单明细：{}",orderDetailList);
        orderDetailMapper.insertBatch(orderDetailList);

        //清除购物车
        cartMapper.clean(BaseContext.getCurrentId());

        OrderSubmitVO vo= OrderSubmitVO.builder().orderAmount(orders.getAmount())
                .orderTime(orders.getOrderTime())
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .build();
        log.info("订单提交成功：{}",vo);
        return vo;
    }

    /**
     * 模拟支付成功
     * @param mun
     */

    @Override
    public void paySuccess(String mun) {
        //更新订单状态
        Orders orders = userOrderMapper.getByNumber(mun);
        if (orders==null){
            log.info("订单不存在:{}",mun);
            return;
        }
        orders.setPayStatus(Orders.PAID);
        orders.setStatus(Orders.TO_BE_CONFIRMED);
        userOrderMapper.updateOrderPaySuccess(orders);
        //发送websocket消息
        HashMap<String, Object> map = new HashMap<>();
        map.put("type", 1);
        map.put("orderId", orders.getId());
        map.put("content","你有新的订单了，请及时处理");
        webSocketServer.sendOrderMessage(JSON.toJSONString(map));
    }

    /**
     * 模拟催单
     * @param orderId
     * @return
     */
    @Override
    public String reminder(Long orderId) {
        //更新订单状态
        Orders orders= userOrderMapper.getByOrderId(orderId);
        if (orders==null){
            log.info("订单不存在");
            return "订单不存在";
        }
        log.info("订单状态：{}",orders);
        orders.setStatus(Orders.TO_BE_CONFIRMED);
        orders.setPayStatus(Orders.PAID);
        userOrderMapper.updateOrderPaySuccess(orders);
        //发送websocket消息
        HashMap<String, Object> map = new HashMap<>();
        map.put("type", 2);
        map.put("orderId", orders.getId());
        map.put("content","用户催单了，请及时处理");
        log.info("发送催单消息：{}",map);
        return webSocketServer.sendReminder(JSON.toJSONString(map));
    }
}
